#include "HistoryFrame.h"
#include "../../core/Impp.h"
#include <wx/splitter.h>
#include <wx/richtext/richtextctrl.h>

namespace Impp
{

BEGIN_EVENT_TABLE(HistoryFrame, wxFrame)
	EVT_TREE_SEL_CHANGED(ID_TREE, HistoryFrame::onSelectionChanged)
END_EVENT_TABLE()


IMPLEMENT_DYNAMIC_CLASS(StdHistoryModule, iModule)

std::vector<HistoryFrame*> HistoryFrame::openedFrames;

HistoryFrame::HistoryFrame(wxWindow* win, Buddy* buddy) :
	wxFrame(win,wxID_ANY,wxT("History")),buddy(buddy),displayedSession(NULL)
{
	wxSplitterWindow* splitter = new wxSplitterWindow(this,wxID_ANY,wxDefaultPosition,wxDefaultSize,wxSP_LIVE_UPDATE);


	tree = new wxTreeCtrl(splitter,ID_TREE,wxDefaultPosition,wxDefaultSize,wxTR_FULL_ROW_HIGHLIGHT|wxTR_HIDE_ROOT|wxTR_DEFAULT_STYLE);



	ModuleManager* modules = Impp::exemplar()->getModuleManager();
	modules->loadAndInit(MODULE_INTERFACE_CHATLOG);

	iModule* module = modules->getModuleByInterface(MODULE_INTERFACE_CHATLOG);
	if(module != NULL){
		if(iChatLogFactory* logFactory = dynamic_cast<iChatLogFactory*>(module)){
			view = logFactory->newChatLog(buddy,splitter,wxID_ANY);
		}else{
			wxASSERT(logFactory != NULL);
		}
	}else{
		wxLogError(wxT("Coudn't create ChatPanel, no Chatlog Module found"));
		wxASSERT(module != NULL);
	}

	/*= new wxTextCtrl(splitter,wxID_ANY,wxEmptyString,wxDefaultPosition,wxDefaultSize,wxTE_MULTILINE|wxTE_RICH2|wxTE_READONLY);*/

	splitter->SplitVertically(tree,view->getWindow(),250);

	root = tree->AddRoot(wxT("History"));

	Database* db = Impp::exemplar()->getDatabase();

	std::vector<int> years;
	db->getHistoryYears(years,buddy);

	if(years.size()!=0){

		wxTreeItemId last;

	   	std::vector<int>::iterator yearIter(years.begin());
	    	for (; yearIter != years.end(); ++yearIter) {
	    		int year = *yearIter;
	    		wxString name;
	    		name << year;
	    		wxTreeItemId yearId = tree->AppendItem(root,name);

	    		std::vector<int> months;
	    		db->getHistoryMonths(months,buddy,year);
	    		wxASSERT(months.size() != 0);

	    		std::vector<int>::iterator monthIter(months.begin());
	    		for (; monthIter != months.end(); ++monthIter) {
	    			int month = *monthIter;
	    			wxTreeItemId monthId = tree->AppendItem(yearId,wxDateTime::GetMonthName((wxDateTime::Month)(month-1)));

	    			std::vector<HistorySession*> sessions;
	    			db->getHistorySessions(sessions,buddy,year,month);
	    			wxASSERT(sessions.size() != 0);

	    			std::vector<HistorySession*>::iterator sessionIter(sessions.begin());

	    			for (; sessionIter != sessions.end(); ++sessionIter) {
	    				HistorySession* session = *sessionIter;

	    				wxTreeItemId sessionId = tree->AppendItem(monthId, session->getSessionStart().Format(wxT("%a %d %b %y (%H:%M)")));
	    				this->sessions.insert(std::pair<wxTreeItemIdValue, HistorySession*>(sessionId.m_pItem,session));
	    				displayedSession = session;
	    				last = sessionId;
	    			}
	    		}
	    		tree->Expand(yearId);
	    	}

	    tree->SelectItem(last,true);
	    writeHistorySession(displayedSession);
	}else{
		//view->WriteText(wxT("no history"));
	}

	//register self;
	HistoryFrame::openedFrames.push_back(this);

	SetSize(600,400);
	Layout();
	CenterOnScreen();
	Show();

}

HistoryFrame::~HistoryFrame()
{
	//deregister self
	std::vector<HistoryFrame*>::iterator dIter(HistoryFrame::openedFrames.begin());
	for (; dIter != HistoryFrame::openedFrames.end(); ++dIter) {
	      if(*dIter==this){
	    	  HistoryFrame::openedFrames.erase(dIter);
	    	  break;
	      }
	}


	std::map<wxTreeItemIdValue,HistorySession*>::iterator sessionIter(sessions.begin());
	for (; sessionIter != sessions.end(); ++sessionIter) {
		delete sessionIter->second;
	}

	delete view;

}

void HistoryFrame::updateOpenFrames(Buddy* buddy){
	std::vector<HistoryFrame*>::iterator dIter(HistoryFrame::openedFrames.begin());
	for (; dIter != HistoryFrame::openedFrames.end(); ++dIter) {
	      (*dIter)->update(buddy);
	}

}


void HistoryFrame::update(Buddy* buddy){
	if(this->buddy !=buddy){
		return;
	}else{
		//wxLogDebug(wxT("right Buddy"));

		HistorySession* session = Impp::exemplar()->getDatabase()->getCurrentHistorySession(buddy);

		if(session!=NULL){
			if(*session == *displayedSession){
				//wxLogDebug(wxT("is session"));
				HistoryEntry* e = displayedSession->getLastEntry();

				if(e != NULL){
					//view->Freeze();
					writeHistoryEntry(e);
					//view->Thaw();
					delete e;
				}else{
					wxLogDebug(wxT("HistoryFrame::update last Session was NULL ???"));
				}
			}
		}else{
			wxLogDebug(wxT("HistoryFrame::buddies session was NULL ???"));
		}


	}
}

void HistoryFrame::writeHistoryEntry(HistoryEntry* entry){
	/*
	if(!view->IsEmpty()){
		view->AppendText(wxT("\n"));
	}

	view->WriteText(wxT(" ("));
	view->WriteText(entry->getTime().FormatTime());
	view->WriteText(wxT(") "));
	Buddy* b = entry->isOutgoing() ? Impp::exemplar()->getSelf() : entry->getBuddy();
	view->WriteText(b->getName());
	view->WriteText(wxT(": "));
	view->WriteText(entry->getMsg());
	*/

	Buddy* b = entry->isOutgoing() ? Impp::exemplar()->getSelf(entry->getBuddy()->getAccountId()) : entry->getBuddy();
	view->writeMessage(entry->getTime(),b,entry->getMsg(),!entry->isOutgoing(),true);
}

void HistoryFrame::writeHistorySession(HistorySession* session){



	std::vector<HistoryEntry*> entries;
	session->getHistoryEntries(entries);



	view->clear();

	//view->SetValue(wxT(""));


	  	std::vector<HistoryEntry*>::iterator dIter(entries.begin());
	  	for (; dIter != entries.end(); ++dIter) {
	  		HistoryEntry* e = *dIter;
	  		writeHistoryEntry(e);
	  		delete e;
	  	}

	displayedSession=session;
}

void HistoryFrame::onSelectionChanged(wxTreeEvent & event){
	wxTreeItemId id = event.GetItem().m_pItem;

	  std::map<wxTreeItemIdValue,HistorySession*>::iterator iter = sessions.find(id.m_pItem);

	  if( iter != sessions.end() ) {
		  HistorySession* session = iter->second;
		  writeHistorySession(session);
	  }



}

void StdHistoryModule::moduleInit(){
	//register Event handler
	Impp* impp = Impp::exemplar();
	impp->Connect(wxID_ANY,EVT_IMPP_COMMAND, ImppCommandEventHandler(StdHistoryModule::onImppCommand), NULL, this);
	impp->Connect(wxID_ANY,EVT_MESSAGE_IN, MessageEventHandler(StdHistoryModule::onMessage), NULL, this);
	impp->Connect(wxID_ANY,EVT_MESSAGE_OUT, MessageEventHandler(StdHistoryModule::onMessage), NULL, this);

	//create Chatwindo Button
	iChatWindow* chatWin = impp->getModuleManager()->getChatWindowModule();
	if(chatWin != NULL){
		chatWin->addActionButtion(STD_HISTROY_MODULE_NAME, STD_HISTORY_MODULE_ACTION_SHOW, wxT("show History"), wxT("show History"));
	}else{
		wxLogDebug(wxT("No Chatwindow found to add Button!"));
	}

	//create BuddyMenuEntry
	iUserInterface* ui = impp->getModuleManager()->getUserInterfaceModule();
	if(ui != NULL){
		ui->reigsterBuddyMenuEntryAdder(STD_HISTROY_MODULE_NAME, StdHistoryModule::addBuddyMenuItem);
		ui->getIcons()->registerActionIcon(STD_HISTROY_MODULE_NAME, STD_HISTORY_MODULE_ACTION_SHOW, wxT("icons/chat/history.png"));
	}else{
		wxLogDebug(wxT("No UserInterface found to add Buddy Menu entry!"));
	}

}
void StdHistoryModule::moduleDestroy(){
	Impp::exemplar()->Disconnect(wxID_ANY,EVT_IMPP_COMMAND, ImppCommandEventHandler(StdHistoryModule::onImppCommand), NULL, this);
	Impp::exemplar()->Disconnect(wxID_ANY,EVT_MESSAGE_IN, MessageEventHandler(StdHistoryModule::onMessage), NULL, this);
	Impp::exemplar()->Disconnect(wxID_ANY,EVT_MESSAGE_OUT, MessageEventHandler(StdHistoryModule::onMessage), NULL, this);
}

void StdHistoryModule::onImppCommand(ImppCommandEvent & event){
	if(event.getModuleName() == STD_HISTROY_MODULE_NAME){
		if(event.getActionName() == STD_HISTORY_MODULE_ACTION_SHOW){
			iBuddyList* bl = Impp::exemplar()->getModuleManager()->getBuddyListModule();
			if(bl != NULL){
				new HistoryFrame(bl->getWindow(), event.getBuddy());
			}else{
				wxLogDebug(wxT("No Buddylist found to show HistoryFrame!"));
			}
		}
	}else{
		event.Skip();
	}
}

void StdHistoryModule::onMessage(MessageEvent & event){
	HistoryFrame::updateOpenFrames(event.getBuddy());
	event.Skip();
}

void wxCALLBACK StdHistoryModule::addBuddyMenuItem(iMenu* menu, Buddy* buddy){
	menu->appendItem(STD_HISTORY_MODULE_ACTION_SHOW, wxT("show History"), 20, wxT("show History"));
}


}
